<!--
 * @Author: wangze@linkstec.com
 * @Date: 2022-02-10 16:10:46
 * @Function: Please Input Function
-->
<template>
  <div class="lk-checkbox-group" :style="{ '--gap': gap }">
    <el-checkbox border :class="{ 'overflow-visible': overflowVisible }" v-model="checkedAll" @change="clickAll" v-if="isShowBx">{{ checkAllLabel }}</el-checkbox>
    <template v-for="option in options">
      <div v-if="option.children" :key="'group_' + option.value" class="children-group">
        <div class="children-group-head">
          <!-- 组头 -->
          <el-checkbox
            v-if="option.children.length"
            :class="{ 'overflow-visible': overflowVisible, 'readonly': readonly }"
            @change="changeAction(option.value, 1)"
            v-model="checkboxGroup[option.value][option.value]"
            border
            :disabled="option.disabled"
            :label="option.value">
            {{ option.label }}
            <slot name="suffix" :option="option"></slot>
            <span class="triangle"></span>
          </el-checkbox>
          <!-- 组头，无组项 -->
          <el-checkbox
            v-else
            :class="{ 'overflow-visible': overflowVisible, 'readonly': readonly }"
            @change="changeAction(option.value, 1)"
            v-model="checkboxGroup[option.value]"
            border
            :disabled="option.disabled"
            :label="option.value">
            {{ option.label }}
            <slot name="suffix" :option="option"></slot>
            <span class="triangle"></span>
          </el-checkbox>
        </div>
        <div class="children-group-list">
          <!-- 组项 -->
          <el-checkbox
            :class="{ 'overflow-visible': overflowVisible, 'readonly': readonly }"
            @change="changeAction(child.value)"
            v-model="checkboxGroup[option.value][child.value]"
            border
            :disabled="child.disabled"
            :label="child.value"
            v-for="child in option.children"
            :key="child.value">
            {{ child.label }}
            <slot name="suffix" :option="child"></slot>
            <span class="triangle"></span>
          </el-checkbox>
        </div>
      </div>
      <!-- 单项 -->
      <el-checkbox
        v-else
        :class="{ 'overflow-visible': overflowVisible, 'readonly': readonly }"
        @change="changeAction(option.value)"
        v-model="checkboxGroup[option.value]"
        border
        :disabled="option.disabled"
        :label="option.value"
        :key="option.value">
        {{ option.label }}
        <slot name="suffix" :option="option"></slot>
        <span class="triangle"></span>
      </el-checkbox>
    </template>
  </div>
</template>

<script>
export default {
  name: 'LkCheckboxGroup',
  props: {
    value: {
      type: Array,
      default: function () {
        return [];
      }
    },
    options: {
      type: Array,
      default: function () {
        return [];
      }
    },
    checkAllLabel: {
      type: String,
      default: '不限'
    },
    // 支持单选；
    isRadio: {
      type: Boolean,
      default: false
    },
    // 是否显示不限
    isShowBx: {
      type: Boolean,
      default: true
    },
    // 是否只读
    readonly: {
      type: Boolean,
      default: false
    },
    // 是否overflow: visible，显示角标时要显示
    overflowVisible: {
      type: Boolean,
      default: false
    },
    // 选项间距
    gap: {
      type: String,
      default: '5px'
    },
    // 选中不限时，是否选中全部
    selectAllWhenSelectBx: {
      type: Boolean,
      default: false
    }
  },
  components: {},
  // 定义属性
  data () {
    const checkboxGroup = {};
    const allValue = [];
    let isTwoDimension = false;
    this.options.map(item => {
      allValue.push(item.value);
      if (item.children && item.children.length) {
        isTwoDimension = true;
        checkboxGroup[item.value] = { [item.value]: this.value.indexOf(item.value) > -1 };
        item.children.map(child => {
          allValue.push(child.value);
          checkboxGroup[item.value][child.value] = this.value.indexOf(child.value) > -1;
        });
      } else {
        checkboxGroup[item.value] = this.value.indexOf(item.value) > -1;
      }
    });
    let checkedAll = false;
    if (this.selectAllWhenSelectBx) {
      checkedAll = this.value.length === allValue.length;
    } else {
      checkedAll = this.value.length === 0;
    }
    return {
      checkedAll,
      checkboxGroup: checkboxGroup,
      allValue,
      valueOrigin: [],
      // 是否是二维选项
      isTwoDimension
    };
  },
  // 计算属性，会监听依赖属性值随之变化
  computed: {},
  // 监控data中的数据变化
  watch: {
    value: {
      handler: function (val) {
        this.checkSelected(val);
        this.options.map(item => {
          if (item.children && item.children.length) {
            this.checkboxGroup[item.value] = { [item.value]: this.value.indexOf(item.value) > -1 };
            item.children.map(child => {
              this.checkboxGroup[item.value][child.value] = this.value.indexOf(child.value) > -1;
            });
          } else {
            this.checkboxGroup[item.value] = this.value.indexOf(item.value) > -1;
          }
        });
      },
      immediate: true
    }
  },
  // 方法集合
  methods: {
    clickAll () {
      if (this.selectAllWhenSelectBx) {
        this.checkedAll ? this.addAll() : this.removeAll();
      } else {
        this.removeAll();
      }
    },
    addAll () {
      let result = this.allValue;
      // disabled的不添加 - 暂不支持二维选项
      if (!this.isTwoDimension) {
        result = this.options.filter(item => {
          const isCheckedOrigin = this.valueOrigin.includes(item.value); // 是否初始化时就选中了
          const isDisabled = item.disabled === true;
          return isCheckedOrigin || !isDisabled;
        }).map(item => item.value);
      }
      this.$emit('input', result);
      this.$emit('change', result);
    },
    removeAll () {
      let result = [];
      // disabled的不移除 - 暂不支持二维选项
      if (!this.isTwoDimension) {
        result = this.options.filter(item => {
          const isChecked = this.value.includes(item.value);
          const isDisabled = item.disabled === true;
          return isChecked && isDisabled;
        }).map(item => item.value);
      }
      this.$emit('input', result);
      this.$emit('change', result);
    },
    // 选择 isSecondAll 二级权限
    changeAction (v, isSecondAll) {
      let inputValue = this.value;
      if (this.isRadio) {
        inputValue = [];
      }

      // 点击了二级选项组的全选
      if (isSecondAll) {
        const allChildrenValues = this.options.find(item => item.value === v).children.map(item => item.value);
        if (this.checkIsIn(v)) {
          // 二级全选取消选中
          inputValue = inputValue.filter(item => !allChildrenValues.includes(item) && item !== v);
        } else {
          // 二级全选选中
          inputValue = [...new Set([...inputValue, ...allChildrenValues])];
          inputValue.push(v);
        }
      }
      // 点击了二级选项组的一项
      else if (!Object.keys(this.checkboxGroup).includes(v)) {
        let parentKey = '';
        this.options.forEach(item => {
          if (item.children && item.children.length) {
            item.children.forEach(item2 => {
              if (item2.value === v) {
                parentKey = item.value;
              }
            });
          }
        });
        if (this.checkIsIn(v)) {
          inputValue = inputValue.filter(item => item !== v);
        } else {
          inputValue.push(v);
        }
        const allChildrenValues = this.options.find(item => item.value === parentKey).children.map(item => item.value);
        const sameGroup = _.intersection(allChildrenValues, inputValue);
        if (sameGroup.length === allChildrenValues.length) {
          // 二级全选选中
          inputValue.push(parentKey);
        } else {
          // 二级全选取消选中
          inputValue = inputValue.filter(item => item !== parentKey);
        }
      }
      // 点击了一级选项
      else {
        // 是否已经选中
        if (this.checkIsIn(v)) {
          // 已选中则删除
          if (this.isRadio && !this.isShowBx) {
            // 当 “单选且不显示无限” 时
            inputValue = [...this.value];
          } else {
            inputValue = inputValue.filter(item => item !== v);
          }
        } else {
          // 未选中则添加
          inputValue.push(v);
        }
      }

      this.$emit('input', inputValue);
      this.$emit('change', inputValue, v);
    },
    // 判断是否存在
    checkIsIn (v) {
      return this.value.indexOf(v) > -1;
    },
    // 检查是否有选中
    checkSelected (value) {
      if (this.selectAllWhenSelectBx) {
        this.checkedAll = value.length === this.allValue.length;
      } else {
        this.checkedAll = value.length === 0;
      }
      // 判断是否全部选中
      this.$emit('isCheckedAll', this.checkedAll);
    }
  },
  // 生命周期 - 创建完成（可以访问当前this实例）
  created () {
    this.valueOrigin = this.value;
  },
  // 生命周期 - 挂载完成（可以访问DOM元素）
  mounted () {},
  beforeCreate () {}, // 生命周期 - 创建之前
  beforeMount () {}, // 生命周期 - 挂载之前
  beforeUpdate () {}, // 生命周期 - 更新之前
  updated () {}, // 生命周期 - 更新之后
  beforeDestroy () {}, // 生命周期 - 销毁之前
  destroyed () {}, // 生命周期 - 销毁完成
  activated () {} // 如果页面有keep-alive缓存功能，这个函数会触发
};
</script>

<style lang='scss' scoped>
.lk-checkbox-group{
  padding-top: 2px;
  box-sizing: border-box;
  line-height: normal;
  margin-bottom: calc(var(--gap) * -1);
  ::v-deep .el-checkbox.is-bordered{
    // & + .el-checkbox.is-bordered{
    //   margin-right: var(--gap);
    // }
    margin-right: var(--gap);
    margin-left: 0;
    margin-bottom: calc(var(--gap) - 4px);
    min-width: 75px;
    padding: 3px 8px;
    height: 28px;
    text-align: center;
    background-color: #FFFFFF;
    overflow: hidden;
    &.is-checked{
      .triangle{
        border-top-color: $--color-primary;
      }
    }
    &:not(.is-checked){
      color: $lk-dark;
    }
    // &:first-of-type{
    //   margin-left: 0;
    // }
    .el-checkbox__input{
      display: none;
    }
    .el-checkbox__label{
      padding-left: 0;
      line-height: 18px;
    }

    &.overflow-visible {
      overflow: visible;
    }
    .el-badge__content.is-fixed {
      z-index: 100;
      transform: translateY(-50%);
      right: -10px;
    }

    &.readonly {
      pointer-events: none;
    }
    &.is-disabled {
      &.is-checked {
        border-color: #0065fb7d;
        .el-checkbox__input.is-disabled + span.el-checkbox__label {
          color: #0065fb7d;
        }
      }
    }
  }
  .children-group {
    display: flex;
    align-items: flex-start;
    &-head {
      padding-top: var(--gap);
      ::v-deep .el-checkbox.is-bordered{
        &.is-checked{
          background: #0065fb;
          .el-checkbox__label {
            color: #fff;
          }
          .triangle{
            border-top-color: #fff;
            display: none;
            &:after {
              border-color: $--color-primary;
            }
          }
        }
      }
    }
    &-list {
      border-radius: calc(var(--gap) / 2);
      padding: var(--gap) 0 0 var(--gap);
    }
  }
  .triangle{
    position: absolute;
    right: 0;
    bottom: 0;
    width: 0;
    height: 0;
    border-top: 8px solid #D4D4D4;
    border-right: 8px solid transparent;
    border-left: 8px solid transparent;
    transform: rotate(-45deg) translate(3px,6px);
    &:after{
      content: ' ';
      display: inline-block;
      position: absolute;
      left: -2px;
      bottom: 4px;
      width: 3px;
      height: 2px;
      border-bottom: 1px solid #fff;
      border-left: 1px solid #fff;
    }
  }
}
</style>
